﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;

namespace HexTileBoard
{
    /// <summary>
    /// Y   reduce speed when zoomed in
    /// Y   consider drawing multiple color icons instead of one scale (add matrix during array resize based on value) (changed scale)
    /// Y   add text indicating menu options
    /// Y   remove pause behaviour on unplug, double check controller behavior; perhaps add popup on disconnect and "a" to continue
    /// </summary>
    public class Board : DrawableGameComponent
    {
        #region Networking Data

        Int32 seed;

        /// <summary>
        /// The network session for the game.
        /// </summary>
        public NetworkSession networkSession;

        /// <summary>
        /// The packet writer for all of the data for the world.
        /// </summary>
        private PacketWriter packetWriter = new PacketWriter();

        /// <summary>
        /// The packet reader for all of the data for the world.
        /// </summary>
        private PacketReader packetReader = new PacketReader();

        /// <summary>
        /// The number of updates that have passed since the world data was sent.
        /// </summary>
        private int updatesSinceWorldDataSend = 0;

        /// <summary>
        /// The number of updates that have passed since a status packet was sent.
        /// </summary>
        private int updatesSinceStatusPacket = 0;

        /// <summary>
        /// The color for tracking the single allowed local player for when it is their turn.
        /// </summary>
        private PlayerColor myColor = PlayerColor.None;

        #endregion

        public int turnCount = 0;//this is a hack to prevent resources handed out due to an error in tilesowned somewhere

        // Board variables
        private short dimension;                 // Number of tiles along positive X-axis increasing, starting at (0,0,0)
        public short Dimension
        {
            get { return dimension; }
        }
        private TileSimple[] tiles;                   // The tiles composing the board
        public TileSimple[] Tiles
        {
            get { return tiles; }
        }
        public List<TileSimple> tilesToUpdate = new List<TileSimple>();    // tiles whose position is being updated gradually, for smooth transitions
        public bool Initialized = false;

        // camera controls
        const float cameraSpeed = 0.004f;
        const float zoomSpeed = 0.8f;
        const float translateSpeed = 1.6f;
        public Cursor cursor;                              // cursor controlled by mouse or gamepad

        // quadtree/Quadtree variables
        public Quadtree quadtree;

        // Player variables
        public Player currentPlayer;
        Dictionary<PlayerColor, Player> players = new Dictionary<PlayerColor, Player>();
        public Dictionary<PlayerColor, Player> Players
        {
            get { return players; }
        }

        // draw components
        private SpriteBatch spriteBatch;
        private Texture2D texAI;
        private float thinkingFade;
        private Texture2D texShadow;
        private Texture2D texWood, texStone, texClay, texWheat, texIron;
        private Texture2D gradient, hexBlue, hexRed, hexGreen, hexYellow;
        private Texture2D texDPad;
        // Draw resource textures, at 64x64, so halfway is 32. Padding is 10% for XBox
        public int widthPadding;
        public int heightPadding;
        public int widthFraction;    // 5 resources, leave right and left values blank for spacing
        public int screenWidth, screenHeight;

        // Sounds
        public SoundEffect cannonSound, constructSound, endSound, errorSound, timerSound, waterSound;

        // Text Components
        public SpriteFont spriteFont, spriteFontSmall;
        public DynamicText dynamicText;

        // Resource Locations
        public Dictionary<HexTileResource, List<TileSimple>> resourcePositions = new Dictionary<HexTileResource, List<TileSimple>>();

        // Billboarding/Particle components
        private Billboard billboard;
        public CannonParticleSystem cannonParticles;
        public SettlingParticleSystem settlingParticles;

        // Selected tile indicators
        Model blueWedge, redWedge, greenWedge, yellowWedge;
        Matrix[] blueTransforms, redTransforms, greenTransforms, yellowTransforms;
        float wedgeRotation = 0.0f;
        float wedgeElevation = 0.0f;
        int maskHeight = 150, maskWidth = 0, upgradeMaskWidth = 0;      // tile icons are either 300x300 or 300x400 - draw smaller at middle of mask, draw larger with small vertical pad
        int maxMaskWidth = 120;
        int tradeWidth = 0;                                             // width of the trading screen
        Texture2D background;
        Texture2D currentGrass, currentWater, currentHill, currentTree;  // the only types of tiles that can be selected
        Texture2D upgradeInfluence1, upgradeInfluence2, upgradeInfluence3, upgradeDefensive, upgradeBridge;
        Texture2D xboxAButton, xboxBButton, xboxXButton, xboxYButton;

        // Game variables
        public bool gameOver = false;
        public PlayerColor winningPlayer = PlayerColor.None;
        public string winningType = "";
        public bool AIThinking = false;
        public bool IsTrading = false;
        public HexTileResource TradingResource;
        public int clayTrade, stoneTrade, wheatTrade, woodTrade;

        // Optimization
        // Change the cursor location every n updates
        Ray cursorUpdateRay = new Ray();
        TileSimple cursorUpdateTile = null;
        short changeCursor = 0;
        int closestTileIndex = -1;

        /// <summary>
        /// The board users will be playing on. Cannot contain more than Short.Max tiles.
        /// The tiling is as follows:
        ///                ^ Z-axis
        ///  T T T T T T T | (forward/back)
        /// T T T T T T T  |
        ///  T T T T T T T |
        /// T T T T T T T  |
        ///  T T T T T T T |
        /// [--------------\
        /// X-axis          \
        /// (left/right)     \
        ///                   V Y-Axis (up/down)
        ///       \/
        ///     Camera
        /// Each tile, excluding those on the edge, has six neighbours to the side and one each to top/bottom.
        /// They are stored in a single dimensional array, with index references to their neighbors.
        /// base.draw and base.update do not need to be called, as they are being handled elsewhere in the screen manager.
        /// </summary>
        public Board(Game game, NetworkSession _networkSession, short _dimension, int _seed,
                    bool _blueIsAI, PlayerIndex? _blueIndex, bool _redIsAI, PlayerIndex? _redIndex,
                    bool _greenIsAI, PlayerIndex? _greenIndex, bool _yellowIsAI, PlayerIndex? _yellowIndex)
            : base(game)
        {
            networkSession = _networkSession;
            if (networkSession == null)
                Initialized = true;

            seed = _seed;

            // Create billboard
            resourcePositions.Add(HexTileResource.Clay, new List<TileSimple>());
            resourcePositions.Add(HexTileResource.Iron, new List<TileSimple>());
            resourcePositions.Add(HexTileResource.Stone, new List<TileSimple>());
            resourcePositions.Add(HexTileResource.Wheat, new List<TileSimple>());
            resourcePositions.Add(HexTileResource.Wood, new List<TileSimple>());
            billboard = new Billboard(game);

            // set up trading variables
            TradingResource = (HexTileResource)BoardConstructor.random.Next(1, 6);
            clayTrade = BoardConstructor.random.Next(2, 5);
            stoneTrade = BoardConstructor.random.Next(2, 5);
            wheatTrade = BoardConstructor.random.Next(2, 5);
            woodTrade = BoardConstructor.random.Next(2, 5);

            // Construct the board
            dimension = _dimension;

            // Construct gameboard with a seed if networking
            if (networkSession == null)
            {
                BoardConstructor.ConstructGameBoard(ref tiles, ref resourcePositions, ref billboard, _dimension, -1);
            }
            else
            {
                BoardConstructor.ConstructGameBoard(ref tiles, ref resourcePositions, ref billboard, _dimension, _seed);
            }


            // Initialize the players. Must be initialized in this order, as game is played in this order and endturn requires it.
            if (_blueIndex != null)
            {
                players.Add(PlayerColor.Blue, new Player(this, PlayerColor.Blue, _blueIsAI, _blueIndex.Value, new Vector3(tiles[tiles.Length / 2].Position.X, tiles[tiles.Length / 2].Position.Y + 400, tiles[tiles.Length / 2].Position.Z - 200), tiles[tiles.Length / 2].Position, game.GraphicsDevice.Viewport));
            }
            if (_redIndex != null)
            {
                players.Add(PlayerColor.Red, new Player(this, PlayerColor.Red, _redIsAI, _redIndex.Value, new Vector3(tiles[tiles.Length / 2].Position.X, tiles[tiles.Length / 2].Position.Y + 400, tiles[tiles.Length / 2].Position.Z - 200), tiles[tiles.Length / 2].Position, game.GraphicsDevice.Viewport));
            }
            if (_greenIndex != null)
            {
                players.Add(PlayerColor.Green, new Player(this, PlayerColor.Green, _greenIsAI, _greenIndex.Value, new Vector3(tiles[tiles.Length / 2].Position.X, tiles[tiles.Length / 2].Position.Y + 400, tiles[tiles.Length / 2].Position.Z - 200), tiles[tiles.Length / 2].Position, game.GraphicsDevice.Viewport));
            }
            if (_yellowIndex != null)
            {
                players.Add(PlayerColor.Yellow, new Player(this, PlayerColor.Yellow, _yellowIsAI, _yellowIndex.Value, new Vector3(tiles[tiles.Length / 2].Position.X, tiles[tiles.Length / 2].Position.Y + 400, tiles[tiles.Length / 2].Position.Z - 200), tiles[tiles.Length / 2].Position, game.GraphicsDevice.Viewport));
            }

            // Set the start color to a random from the selected colors
            int i = 0;
            int startTurn = BoardConstructor.random.Next(0, players.Count);
            foreach (KeyValuePair<PlayerColor, Player> p in players)
            {
                if (i == startTurn)
                {
                    currentPlayer = p.Value;
                    break;
                }

                i++;
            }

            // Create the cursor
            cursor = new Cursor(game);
            game.Components.Add(cursor);

            cursor.currentPlayerIndex = currentPlayer.playerIndex;
            cursor.PlayerIsAI = currentPlayer.IsAI;

            // Initialize dynamic text
            dynamicText = new DynamicText(game);
        }

        /// <summary>
        /// Initialize any necessary game components.
        /// </summary>
        public override void Initialize()
        {
            dynamicText.Initialize();

            base.Initialize();
        }

        /// <summary>
        /// Load any necessary game components.
        /// </summary>
        public new void LoadContent()
        {
            // Load instanced models and staff quadtree
            ContentManager content = new ContentManager(this.Game.Services, "Content");
            BoardConstructor.ConstructQuadTreeAndInstancing(content, this.Game.GraphicsDevice, tiles, ref quadtree, dimension);

            // Particle systems
            cannonParticles = new CannonParticleSystem(this.Game, content);
            cannonParticles.Initialize();
            settlingParticles = new SettlingParticleSystem(this.Game, content);
            settlingParticles.Initialize();

            // Load textures
            background = content.Load<Texture2D>("Textures/Screens/background1");
            texAI = content.Load<Texture2D>("Textures/Icons/ai");
            texShadow = content.Load<Texture2D>("Textures/Resources/shadow_s");
            texClay = content.Load<Texture2D>("Textures/Resources/clay_s");
            texIron = content.Load<Texture2D>("Textures/Resources/iron_s");
            texStone = content.Load<Texture2D>("Textures/Resources/stone_s");
            texWheat = content.Load<Texture2D>("Textures/Resources/wheat_s");
            texWood = content.Load<Texture2D>("Textures/Resources/wood_s");
            hexBlue = content.Load<Texture2D>("Textures/Resources/hex_blue");
            hexGreen = content.Load<Texture2D>("Textures/Resources/hex_green");
            hexRed = content.Load<Texture2D>("Textures/Resources/hex_red");
            hexYellow = content.Load<Texture2D>("Textures/Resources/hex_yellow");
            gradient = content.Load<Texture2D>("Textures/Screens/gradient");

            // 300x300 icons
            currentWater = content.Load<Texture2D>("Textures/Icons/texWater");
            currentGrass = content.Load<Texture2D>("Textures/Icons/texGrass");
            currentHill = content.Load<Texture2D>("Textures/Icons/texHill");
            currentTree = content.Load<Texture2D>("Textures/Icons/texTree");
            upgradeBridge = content.Load<Texture2D>("Textures/Icons/texBridge");
            upgradeDefensive = content.Load<Texture2D>("Textures/Icons/texDefensive");
            // 300x400 icons
            upgradeInfluence1 = content.Load<Texture2D>("Textures/Icons/texOffensive1");
            upgradeInfluence2 = content.Load<Texture2D>("Textures/Icons/texOffensive2");
            upgradeInfluence3 = content.Load<Texture2D>("Textures/Icons/texOffensive3");

            // Button images
            xboxXButton = content.Load<Texture2D>("Textures/Icons/xboxControllerButtonX");
            xboxAButton = content.Load<Texture2D>("Textures/Icons/xboxControllerButtonA");
            xboxBButton = content.Load<Texture2D>("Textures/Icons/xboxControllerButtonB");
            xboxYButton = content.Load<Texture2D>("Textures/Icons/xboxControllerButtonY");
            texDPad = content.Load<Texture2D>("Textures/Icons/xboxControllerDPad");

            // Load sounds
            cannonSound = content.Load<SoundEffect>("Sounds/cannon");
            constructSound = content.Load<SoundEffect>("Sounds/construct");
            endSound = content.Load<SoundEffect>("Sounds/end");
            errorSound = content.Load<SoundEffect>("Sounds/error");
            timerSound = content.Load<SoundEffect>("Sounds/timer");
            waterSound = content.Load<SoundEffect>("Sounds/water");

            // init sprite batch
            spriteBatch = new SpriteBatch(InstancedDictionaries.instancedGraphicsDevice);

            // Load fonts
            spriteFont = content.Load<SpriteFont>("Fonts/gameFont");
            spriteFontSmall = content.Load<SpriteFont>("Fonts/gameFontSmall");

            // Finalize and cleanup
            base.LoadContent();
            GC.Collect();

            // Get dimensions for drawing assist
            widthPadding = InstancedDictionaries.instancedGraphicsDevice.Viewport.Bounds.Width / 10;
            heightPadding = InstancedDictionaries.instancedGraphicsDevice.Viewport.Bounds.Height / 10;
            widthFraction = InstancedDictionaries.instancedGraphicsDevice.Viewport.Bounds.Width / 7;    // 5 resources, leave right and left values blank for spacing
            screenHeight = InstancedDictionaries.instancedGraphicsDevice.Viewport.Bounds.Height;
            screenWidth = InstancedDictionaries.instancedGraphicsDevice.Viewport.Bounds.Width;
            maxMaskWidth += widthPadding;

            // Load models
            blueWedge = content.Load<Model>("Models/blueWedge");
            redWedge = content.Load<Model>("Models/redWedge");
            greenWedge = content.Load<Model>("Models/greenWedge");
            yellowWedge = content.Load<Model>("Models/yellowWedge");
            blueTransforms = new Matrix[blueWedge.Bones.Count];
            redTransforms = new Matrix[redWedge.Bones.Count];
            greenTransforms = new Matrix[greenWedge.Bones.Count];
            yellowTransforms = new Matrix[yellowWedge.Bones.Count];
            blueWedge.CopyAbsoluteBoneTransformsTo(blueTransforms);
            redWedge.CopyAbsoluteBoneTransformsTo(redTransforms);
            greenWedge.CopyAbsoluteBoneTransformsTo(greenTransforms);
            yellowWedge.CopyAbsoluteBoneTransformsTo(yellowTransforms);
        }

        public new void UnloadContent()
        {
            this.gameOver = true;
            this.Game.Components.Remove(cursor);
            cursor = null;

            base.UnloadContent();
        }

        public void restarting()
        {
            this.gameOver = true;
            this.Game.Components.Remove(cursor);
            cursor = null;
        }

        public override void Draw(GameTime gameTime)
        {
            // Set renderstates for drawing 3D models.
            this.Game.GraphicsDevice.BlendState = BlendState.Opaque;
            this.Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;

            //BoardConstructor.objectsDrawn = 0;
            //BoardConstructor.branchesVisited = 0;

            // Update the lights ViewProjection matrix based on the current camera frustum. Call once per draw
            InstancedDrawing.lightViewProjection = InstancedDrawing.CreateLightViewProjectionMatrix(currentPlayer.Camera.ViewFrustum);

            // Draw shadows
            // Draw all the instances, using the currently selected rendering technique.
            // Set our render target to our floating point render target
            InstancedDictionaries.instancedGraphicsDevice.SetRenderTarget(InstancedDrawing.shadowRenderTarget);

            // Clear the render target to white or all 1's. We set the clear to white since that represents the furthest the object could be away
            InstancedDictionaries.instancedGraphicsDevice.Clear(Color.White);
            quadtree.DrawVisibleInstancedListsByDiscovery(gameTime, currentPlayer.Camera, true);

            // Draw the models after drawing the shadow map
            // Set render target back to the back buffer
            InstancedDictionaries.instancedGraphicsDevice.SetRenderTarget(null);

            // Draw background
            spriteBatch.Begin();
            spriteBatch.Draw(background, new Rectangle(0, 0, 1280, 720), Color.White);
            spriteBatch.Draw(gradient, new Rectangle(0, 0, 1280, 720), new Color(0.6f, 0.6f, 0.6f, 0.6f));
            spriteBatch.End();

            // Reset for 3D targets
            this.Game.GraphicsDevice.BlendState = BlendState.Opaque;
            this.Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            InstancedDictionaries.instancedGraphicsDevice.SamplerStates[1] = Microsoft.Xna.Framework.Graphics.SamplerState.PointClamp;
            quadtree.DrawVisibleInstancedListsByDiscovery(gameTime, currentPlayer.Camera, false);

            // Draw billboards
            billboard.DrawBillboards(currentPlayer.Camera);

            // Draw particles
            cannonParticles.SetCamera(currentPlayer.Camera.ViewMatrix, currentPlayer.Camera.ProjectionMatrix);
            settlingParticles.SetCamera(currentPlayer.Camera.ViewMatrix, currentPlayer.Camera.ProjectionMatrix);
            cannonParticles.Draw(gameTime);
            settlingParticles.Draw(gameTime);

            // Draw selected tile model
            if (currentPlayer.SelectedTile != null)
            {
                switch (currentPlayer.Side)
                {
                    case PlayerColor.Blue:
                        DrawModel(blueWedge, Matrix.CreateRotationY(wedgeRotation) * Matrix.CreateTranslation(new Vector3(currentPlayer.SelectedTile.Position.X, wedgeElevation, currentPlayer.SelectedTile.Position.Z)), blueTransforms); break;
                    case PlayerColor.Red:
                        DrawModel(redWedge, Matrix.CreateRotationY(wedgeRotation) * Matrix.CreateTranslation(new Vector3(currentPlayer.SelectedTile.Position.X, wedgeElevation, currentPlayer.SelectedTile.Position.Z)), redTransforms); break;
                    case PlayerColor.Green:
                        DrawModel(greenWedge, Matrix.CreateRotationY(wedgeRotation) * Matrix.CreateTranslation(new Vector3(currentPlayer.SelectedTile.Position.X, wedgeElevation, currentPlayer.SelectedTile.Position.Z)), greenTransforms); break;
                    case PlayerColor.Yellow:
                        DrawModel(yellowWedge, Matrix.CreateRotationY(wedgeRotation) * Matrix.CreateTranslation(new Vector3(currentPlayer.SelectedTile.Position.X, wedgeElevation, currentPlayer.SelectedTile.Position.Z)), yellowTransforms); break;
                }
            }

            // Draw UI Components
            spriteBatch.Begin();

            // draw textures
            spriteBatch.Draw(gradient, new Rectangle(widthFraction - 20, (heightPadding * 9) - 74, screenWidth - (widthFraction * 2) - 20, 84), new Color(0.7f, 0.7f, 0.7f, 0.7f));
            if (!currentPlayer.canBuildFirst && !IsTrading && !currentPlayer.IsAI)
                spriteBatch.Draw(texDPad, new Rectangle((screenWidth / 2) - 46, heightPadding * 9 - 120, 92, 46), new Rectangle(0, 0, 186, 93), Color.White);
            spriteBatch.Draw(texShadow, new Rectangle(widthFraction, (heightPadding * 9) - 44, 90, 48), Color.White);
            spriteBatch.Draw(texShadow, new Rectangle(widthFraction * 2, (heightPadding * 9) - 44, 90, 48), Color.White);
            spriteBatch.Draw(texShadow, new Rectangle(widthFraction * 3, (heightPadding * 9) - 44, 90, 48), Color.White);
            spriteBatch.Draw(texShadow, new Rectangle(widthFraction * 4, (heightPadding * 9) - 44, 90, 48), Color.White);
            spriteBatch.Draw(texShadow, new Rectangle(widthFraction * 5, (heightPadding * 9) - 44, 90, 48), Color.White);
            spriteBatch.Draw(texClay, new Rectangle(widthFraction, (heightPadding * 9) - 64, 80, 64), Color.White);
            spriteBatch.Draw(texIron, new Rectangle(widthFraction * 2, (heightPadding * 9) - 64, 80, 64), Color.White);
            spriteBatch.Draw(texStone, new Rectangle(widthFraction * 3, (heightPadding * 9) - 64, 80, 64), Color.White);
            spriteBatch.Draw(texWheat, new Rectangle(widthFraction * 4, (heightPadding * 9) - 64, 80, 64), Color.White);
            spriteBatch.Draw(texWood, new Rectangle(widthFraction * 5, (heightPadding * 9) - 64, 80, 64), Color.White);

            // draw values
            spriteBatch.DrawString(spriteFont, currentPlayer.CurrentResources[HexTileResource.Clay].ToString(), new Vector2(widthFraction + 100, heightPadding * 9 - 44), Color.White);
            spriteBatch.DrawString(spriteFont, currentPlayer.CurrentResources[HexTileResource.Iron].ToString(), new Vector2(widthFraction * 2 + 100, heightPadding * 9 - 44), Color.White);
            spriteBatch.DrawString(spriteFont, currentPlayer.CurrentResources[HexTileResource.Stone].ToString(), new Vector2(widthFraction * 3 + 100, heightPadding * 9 - 44), Color.White);
            spriteBatch.DrawString(spriteFont, currentPlayer.CurrentResources[HexTileResource.Wheat].ToString(), new Vector2(widthFraction * 4 + 100, heightPadding * 9 - 44), Color.White);
            spriteBatch.DrawString(spriteFont, currentPlayer.CurrentResources[HexTileResource.Wood].ToString(), new Vector2(widthFraction * 5 + 100, heightPadding * 9 - 44), Color.White);

            // Draw current turn and end turn
            spriteBatch.Draw(gradient, new Rectangle(widthPadding - 10, heightPadding - 10, 200, 85), new Color(0.5f, 0.5f, 0.5f, 0.5f));
            switch (currentPlayer.Side)
            {
                case PlayerColor.Blue:
                    spriteBatch.Draw(hexBlue, new Rectangle(widthPadding - 3, heightPadding, 35, 32), Color.White); break;
                case PlayerColor.Red:
                    spriteBatch.Draw(hexRed, new Rectangle(widthPadding - 3, heightPadding, 35, 32), Color.White); break;
                case PlayerColor.Green:
                    spriteBatch.Draw(hexGreen, new Rectangle(widthPadding - 3, heightPadding, 35, 32), Color.White); break;
                case PlayerColor.Yellow:
                    spriteBatch.Draw(hexYellow, new Rectangle(widthPadding - 3, heightPadding, 35, 32), Color.White); break;
            }
            if (currentPlayer.tilesOwned.Count > 0)
            {
                // Force the turn to be over if we have won
                if (currentPlayer.tilesOwned.Count / (float)tiles.Length >= BoardVariables.PercentOfBoard && !gameOver)
                    currentPlayer.EndTurn();
                spriteBatch.DrawString(spriteFontSmall, "  Occupied: " + (int)((currentPlayer.tilesOwned.Count / (float)tiles.Length) * 100) + "%", new Vector2(widthPadding - 10, heightPadding + 40), Color.White);
            }
            if (!AIThinking)
            {
                spriteBatch.DrawString(spriteFontSmall, "End Turn: ", new Vector2(widthPadding + 40, heightPadding), Color.White);
                spriteBatch.Draw(xboxYButton, new Rectangle(widthPadding + 150, heightPadding, 32, 32), Color.White);
            }

            // Draw selected tile items
            if (!currentPlayer.IsAI)
            {
                spriteBatch.Draw(gradient, new Rectangle(screenWidth - maskWidth, heightPadding, maskWidth, maskHeight), new Color(0.8f, 0.8f, 0.8f, 0.8f));
                spriteBatch.Draw(gradient, new Rectangle(screenWidth - maskWidth, heightPadding + maskHeight + 20, maskWidth, 10), Color.DarkGray);
                spriteBatch.Draw(gradient, new Rectangle(screenWidth - upgradeMaskWidth, heightPadding + maskHeight + 40, upgradeMaskWidth, maskHeight + 40), new Color(0.8f, 0.8f, 0.8f, 0.8f));
                if (currentPlayer.SelectedTile != null)
                {
                    if (maxMaskWidth == maskWidth)    // Draw relevant icons when fully expanded
                    {
                        // Draw currently selected tile items
                        if (currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.None)
                        {
                            if (currentPlayer.SelectedTile.TileBase == HexTileBase.Grass)
                            {
                                if (currentPlayer.SelectedTile.NaturalModifier == HexTileNaturalModifier.Hill2 || currentPlayer.SelectedTile.NaturalModifier == HexTileNaturalModifier.Hill2 || currentPlayer.SelectedTile.NaturalModifier == HexTileNaturalModifier.Hill2)
                                {
                                    spriteBatch.Draw(currentHill, new Rectangle(screenWidth - maskWidth + 10, heightPadding + 25, 100, 100), Color.White);
                                    if (maxMaskWidth == upgradeMaskWidth)
                                    {
                                        spriteBatch.Draw(upgradeDefensive, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 65, 100, 100), Color.White);
                                        spriteBatch.DrawString(spriteFontSmall, "    :" + BoardVariables.DefensiveClayCost + "    :" + BoardVariables.DefensiveStoneCost + " \n    :" + BoardVariables.DefensiveWoodCost, new Vector2(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160), Color.White);
                                        spriteBatch.Draw(texClay, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                        spriteBatch.Draw(texStone, new Rectangle(screenWidth - maskWidth + 85, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                        spriteBatch.Draw(texWood, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 195, 32, 32), Color.White);

                                        if (currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.DefensiveWoodCost && currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.DefensiveStoneCost && currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.DefensiveClayCost)
                                        {
                                            spriteBatch.Draw(xboxXButton, new Rectangle(screenWidth - maskWidth + 120, heightPadding + maskHeight + 100, 40, 40), Color.White * (((float)Math.Sin(gameTime.TotalGameTime.TotalSeconds * 4) + 1) * 0.5f));
                                        }
                                    }
                                }
                                else if (currentPlayer.SelectedTile.NaturalModifier == HexTileNaturalModifier.Trees1 || currentPlayer.SelectedTile.NaturalModifier == HexTileNaturalModifier.Trees1)
                                {
                                    spriteBatch.Draw(currentTree, new Rectangle(screenWidth - maskWidth + 10, heightPadding + 25, 100, 100), Color.White);
                                    if (maxMaskWidth == upgradeMaskWidth)
                                    {
                                        spriteBatch.Draw(upgradeInfluence1, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 40 + 25, 100, 100), Color.White);
                                        spriteBatch.DrawString(spriteFontSmall, "    :" + BoardVariables.Influence1ClayCost + "      :" + BoardVariables.Influence1StoneCost + " \n    :" + BoardVariables.Influence1WheatCost + "      :" + BoardVariables.Influence1WoodCost, new Vector2(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160), Color.White);
                                        spriteBatch.Draw(texClay, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                        spriteBatch.Draw(texStone, new Rectangle(screenWidth - maskWidth + 85, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                        spriteBatch.Draw(texWheat, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 195, 32, 32), Color.White);
                                        spriteBatch.Draw(texWood, new Rectangle(screenWidth - maskWidth + 85, heightPadding + maskHeight + 195, 32, 32), Color.White);

                                        if (currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.Influence1WoodCost && currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.Influence1StoneCost && currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.Influence1ClayCost && currentPlayer.CurrentResources[HexTileResource.Wheat] >= BoardVariables.Influence1WheatCost)
                                        {
                                            spriteBatch.Draw(xboxXButton, new Rectangle(screenWidth - maskWidth + 120, heightPadding + maskHeight + 100, 40, 40), Color.White * (((float)Math.Sin(gameTime.TotalGameTime.TotalSeconds * 4) + 1) * 0.5f));
                                        }
                                    }
                                }
                                else if (currentPlayer.SelectedTile.NaturalModifier == HexTileNaturalModifier.None)
                                {
                                    spriteBatch.Draw(currentGrass, new Rectangle(screenWidth - maskWidth + 10, heightPadding + 25, 100, 100), Color.White);
                                    if (maxMaskWidth == upgradeMaskWidth)
                                    {
                                        spriteBatch.Draw(upgradeInfluence1, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 40 + 25, 100, 100), Color.White);
                                        spriteBatch.DrawString(spriteFontSmall, "    :" + BoardVariables.Influence1ClayCost + "      :" + BoardVariables.Influence1StoneCost + " \n    :" + BoardVariables.Influence1WheatCost + "      :" + BoardVariables.Influence1WoodCost, new Vector2(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160), Color.White);
                                        spriteBatch.Draw(texClay, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                        spriteBatch.Draw(texStone, new Rectangle(screenWidth - maskWidth + 85, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                        spriteBatch.Draw(texWheat, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 195, 32, 32), Color.White);
                                        spriteBatch.Draw(texWood, new Rectangle(screenWidth - maskWidth + 85, heightPadding + maskHeight + 195, 32, 32), Color.White);

                                        if (currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.Influence1WoodCost && currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.Influence1StoneCost && currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.Influence1ClayCost && currentPlayer.CurrentResources[HexTileResource.Wheat] >= BoardVariables.Influence1WheatCost)
                                        {
                                            spriteBatch.Draw(xboxXButton, new Rectangle(screenWidth - maskWidth + 120, heightPadding + maskHeight + 100, 40, 40), Color.White * (((float)Math.Sin(gameTime.TotalGameTime.TotalSeconds * 4) + 1) * 0.5f));
                                        }
                                    }
                                }
                            }
                            else if (currentPlayer.SelectedTile.TileBase == HexTileBase.Water)
                            {
                                spriteBatch.Draw(currentWater, new Rectangle(screenWidth - maskWidth + 10, heightPadding + 25, 100, 100), Color.White);
                                if (maxMaskWidth == upgradeMaskWidth)
                                {
                                    spriteBatch.Draw(upgradeBridge, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 40 + 25, 100, 100), Color.White);
                                    spriteBatch.DrawString(spriteFontSmall, "    :" + BoardVariables.BridgeClayCost + "      :" + BoardVariables.BridgeStoneCost + " \n    :" + BoardVariables.BridgeWoodCost, new Vector2(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160), Color.White);
                                    spriteBatch.Draw(texClay, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                    spriteBatch.Draw(texStone, new Rectangle(screenWidth - maskWidth + 85, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                    spriteBatch.Draw(texWood, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 195, 32, 32), Color.White);

                                    if (currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.BridgeWoodCost && currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.BridgeStoneCost && currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.BridgeClayCost)
                                    {
                                        spriteBatch.Draw(xboxXButton, new Rectangle(screenWidth - maskWidth + 120, heightPadding + maskHeight + 100, 40, 40), Color.White * (((float)Math.Sin(gameTime.TotalGameTime.TotalSeconds * 4) + 1) * 0.5f));
                                    }
                                }
                            }
                        }
                        else
                        {
                            switch (currentPlayer.SelectedTile.ManMadeModifier)
                            {
                                case HexTileManMadeModifier.Bridge:
                                    spriteBatch.Draw(upgradeBridge, new Rectangle(screenWidth - maskWidth + 10, heightPadding + 25, 100, 100), Color.White); break;
                                case HexTileManMadeModifier.DefensiveTower:
                                    spriteBatch.Draw(upgradeDefensive, new Rectangle(screenWidth - maskWidth + 10, heightPadding + 25, 100, 100), Color.White); break;
                                case HexTileManMadeModifier.InfluenceTower1:
                                    spriteBatch.Draw(upgradeInfluence1, new Rectangle(screenWidth - maskWidth + 10, heightPadding + 8, 100, 133), Color.White);
                                    if (maxMaskWidth == upgradeMaskWidth)
                                    {
                                        spriteBatch.Draw(upgradeInfluence2, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 40 + 25, 100, 100), Color.White);
                                        spriteBatch.DrawString(spriteFontSmall, "    :" + BoardVariables.Influence2ClayCost + "     :" + BoardVariables.Influence2StoneCost + " \n    :" + BoardVariables.Influence2WheatCost + "      :" + BoardVariables.Influence2WoodCost, new Vector2(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160), Color.White);
                                        spriteBatch.Draw(texClay, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                        spriteBatch.Draw(texStone, new Rectangle(screenWidth - maskWidth + 85, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                        spriteBatch.Draw(texWheat, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 195, 32, 32), Color.White);
                                        spriteBatch.Draw(texWood, new Rectangle(screenWidth - maskWidth + 85, heightPadding + maskHeight + 195, 32, 32), Color.White);

                                        if (currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.Influence2WoodCost && currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.Influence2StoneCost && currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.Influence2ClayCost && currentPlayer.CurrentResources[HexTileResource.Wheat] >= BoardVariables.Influence2WheatCost)
                                        {
                                            spriteBatch.Draw(xboxXButton, new Rectangle(screenWidth - maskWidth + 120, heightPadding + maskHeight + 100, 40, 40), Color.White * (((float)Math.Sin(gameTime.TotalGameTime.TotalSeconds * 4) + 1) * 0.5f));
                                        }
                                    } break;
                                case HexTileManMadeModifier.InfluenceTower2:
                                    spriteBatch.Draw(upgradeInfluence2, new Rectangle(screenWidth - maskWidth + 10, heightPadding + 8, 100, 133), Color.White);
                                    if (maxMaskWidth == upgradeMaskWidth)
                                    {
                                        spriteBatch.Draw(upgradeInfluence3, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 40 + 25, 100, 100), Color.White);
                                        spriteBatch.DrawString(spriteFontSmall, "    :" + BoardVariables.Influence3ClayCost + "     :" + BoardVariables.Influence3StoneCost + " \n    :" + BoardVariables.Influence3WheatCost + "      :" + BoardVariables.Influence3WoodCost, new Vector2(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160), Color.White);
                                        spriteBatch.Draw(texClay, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                        spriteBatch.Draw(texStone, new Rectangle(screenWidth - maskWidth + 85, heightPadding + maskHeight + 160, 32, 32), Color.White);
                                        spriteBatch.Draw(texWheat, new Rectangle(screenWidth - maskWidth + 10, heightPadding + maskHeight + 195, 32, 32), Color.White);
                                        spriteBatch.Draw(texWood, new Rectangle(screenWidth - maskWidth + 85, heightPadding + maskHeight + 195, 32, 32), Color.White);

                                        if (currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.Influence3WoodCost && currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.Influence3StoneCost && currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.Influence3ClayCost && currentPlayer.CurrentResources[HexTileResource.Wheat] >= BoardVariables.Influence3WheatCost)
                                        {
                                            spriteBatch.Draw(xboxXButton, new Rectangle(screenWidth - maskWidth + 120, heightPadding + maskHeight + 100, 40, 40), Color.White * (((float)Math.Sin(gameTime.TotalGameTime.TotalSeconds * 4) + 1) * 0.5f));
                                        }
                                    } break;
                                case HexTileManMadeModifier.InfluenceTower3:
                                    spriteBatch.Draw(upgradeInfluence3, new Rectangle(screenWidth - maskWidth + 10, heightPadding + 8, 100, 133), Color.White); break;
                            }
                        }
                    }
                }
            }

            // Draw costs and user text
            if (cursor.currentTexture == Cursor.CursorTexture.Target)
            {
                spriteBatch.Draw(xboxAButton, new Rectangle((int)cursor.Position.X - 16, (int)cursor.Position.Y - 40, 32, 32), Color.White);
                spriteBatch.DrawString(spriteFontSmall, "Iron: " + BoardVariables.CannonFiringCost, new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("Iron: " + BoardVariables.CannonFiringCost).X / 2) + 2, cursor.Position.Y + spriteFontSmall.LineSpacing + 2), Color.Black);
                spriteBatch.DrawString(spriteFontSmall, "Iron: " + BoardVariables.CannonFiringCost, new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("Iron: " + BoardVariables.CannonFiringCost).X / 2), cursor.Position.Y + spriteFontSmall.LineSpacing), Color.White);
            }
            else if (cursor.currentTexture == Cursor.CursorTexture.NoTarget)
            {
                if (currentPlayer.CurrentResources[HexTileResource.Iron] == 0)
                {
                    spriteBatch.DrawString(spriteFontSmall, "Need " + BoardVariables.CannonFiringCost + " Iron", new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("Need " + BoardVariables.CannonFiringCost + " Iron").X / 2) + 2, cursor.Position.Y + spriteFontSmall.LineSpacing + 2), Color.Black);
                    spriteBatch.DrawString(spriteFontSmall, "Need " + BoardVariables.CannonFiringCost + " Iron", new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("Need " + BoardVariables.CannonFiringCost + " Iron").X / 2), cursor.Position.Y + spriteFontSmall.LineSpacing), Color.White);
                }
                else if (cursorUpdateTile.ManMadeModifier == HexTileManMadeModifier.DefensiveTower)
                {
                    spriteBatch.DrawString(spriteFontSmall, "Cannot attack defensive towers", new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("Cannot attack defensive towers").X / 2) + 2, cursor.Position.Y + spriteFontSmall.LineSpacing + 2), Color.Black);
                    spriteBatch.DrawString(spriteFontSmall, "Cannot attack defensive towers", new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("Cannot attack defensive towers").X / 2), cursor.Position.Y + spriteFontSmall.LineSpacing), Color.White);
                }
                else if (currentPlayer.tilesOwned.Count > 0) 
                {
                    spriteBatch.DrawString(spriteFontSmall, "No tower close enough to attack this.", new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("No tower close enough to attack this.").X / 2) + 2, cursor.Position.Y + spriteFontSmall.LineSpacing + 2), Color.Black);
                    spriteBatch.DrawString(spriteFontSmall, "No tower close enough to attack this.", new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("No tower close enough to attack this.").X / 2), cursor.Position.Y + spriteFontSmall.LineSpacing), Color.White);
                }
                //else if (currentPlayer.SelectedTile != null && currentPlayer.SelectedTile.ManMadeModifier != HexTileManMadeModifier.DefensiveTower)
                //{
                //    spriteBatch.DrawString(spriteFontSmall, "Distance is " + (int)(Vector3.Distance(currentPlayer.SelectedTile.Position, cursorUpdateTile.Position) + 1) + "\n Can shoot " + (BoardVariables.cannonDistance * (int)currentPlayer.SelectedTile.ManMadeModifier), new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("Distance is 100").X / 2) + 2, cursor.Position.Y + spriteFontSmall.LineSpacing + 2), Color.Black);
                //    spriteBatch.DrawString(spriteFontSmall, "Distance is " + (int)(Vector3.Distance(currentPlayer.SelectedTile.Position, cursorUpdateTile.Position) + 1) + "\n Can shoot " + (BoardVariables.cannonDistance * (int)currentPlayer.SelectedTile.ManMadeModifier), new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("Distance is 100").X / 2), cursor.Position.Y + spriteFontSmall.LineSpacing), Color.White);
                //}
                //else if (currentPlayer.SelectedTile != null && currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.DefensiveTower)
                //{
                //    spriteBatch.DrawString(spriteFontSmall, "Distance is " + (int)(Vector3.Distance(currentPlayer.SelectedTile.Position, cursorUpdateTile.Position) + 1) + "\n Can shoot " + (BoardVariables.cannonDistance), new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("Distance is 100").X / 2) + 2, cursor.Position.Y + spriteFontSmall.LineSpacing + 2), Color.Black);
                //    spriteBatch.DrawString(spriteFontSmall, "Distance is " + (int)(Vector3.Distance(currentPlayer.SelectedTile.Position, cursorUpdateTile.Position) + 1) + "\n Can shoot " + (BoardVariables.cannonDistance), new Vector2(cursor.Position.X - (spriteFontSmall.MeasureString("Distance is 100").X / 2), cursor.Position.Y + spriteFontSmall.LineSpacing), Color.White);
                //}
            }

            // Draw game over materials
            if (gameOver)
            {
                spriteBatch.Draw(gradient, new Rectangle(widthPadding, heightPadding, widthPadding * 8, heightPadding * 8), new Color(0.7f, 0.7f, 0.7f, 0.7f));
                switch (winningPlayer)
                {
                    case PlayerColor.Blue:
                        spriteBatch.Draw(hexBlue, new Rectangle((screenWidth / 2) - 125, (screenHeight / 2) - 140, 250, 220), Color.White);
                        spriteBatch.DrawString(spriteFont, "Blue has won!", new Vector2((screenWidth / 2) - (spriteFont.MeasureString("Blue has won!").X / 2) + 2, (screenHeight / 2) + 102), Color.Black);
                        spriteBatch.DrawString(spriteFont, "Blue has won!", new Vector2((screenWidth / 2) - (spriteFont.MeasureString("Blue has won!").X / 2), (screenHeight / 2) + 100), Color.White);
                        break;
                    case PlayerColor.Red:
                        spriteBatch.Draw(hexRed, new Rectangle((screenWidth / 2) - 125, (screenHeight / 2) - 140, 250, 220), Color.White);
                        spriteBatch.DrawString(spriteFont, "Red has won!", new Vector2((screenWidth / 2) - (spriteFont.MeasureString("Red has won!").X / 2) + 2, (screenHeight / 2) + 102), Color.Black);
                        spriteBatch.DrawString(spriteFont, "Red has won!", new Vector2((screenWidth / 2) - (spriteFont.MeasureString("Red has won!").X / 2), (screenHeight / 2) + 100), Color.White);
                        break;
                    case PlayerColor.Green:
                        spriteBatch.Draw(hexGreen, new Rectangle((screenWidth / 2) - 125, (screenHeight / 2) - 140, 250, 220), Color.White);
                        spriteBatch.DrawString(spriteFont, "Green has won!", new Vector2((screenWidth / 2) - (spriteFont.MeasureString("Green has won!").X / 2) + 2, (screenHeight / 2) + 102), Color.Black);
                        spriteBatch.DrawString(spriteFont, "Green has won!", new Vector2((screenWidth / 2) - (spriteFont.MeasureString("Green has won!").X / 2), (screenHeight / 2) + 100), Color.White);
                        break;
                    case PlayerColor.Yellow:
                        spriteBatch.Draw(hexYellow, new Rectangle((screenWidth / 2) - 125, (screenHeight / 2) - 140, 250, 220), Color.White);
                        spriteBatch.DrawString(spriteFont, "Yellow has won!", new Vector2((screenWidth / 2) - (spriteFont.MeasureString("Yellow has won!").X / 2) + 2, (screenHeight / 2) + 102), Color.Black);
                        spriteBatch.DrawString(spriteFont, "Yellow has won!", new Vector2((screenWidth / 2) - (spriteFont.MeasureString("Yellow has won!").X / 2), (screenHeight / 2) + 100), Color.White);
                        break;
                }
                spriteBatch.DrawString(spriteFont, winningType, new Vector2((screenWidth / 2) - (spriteFont.MeasureString(winningType).X / 2) + 2, (screenHeight / 2) + 132), Color.Black);
                spriteBatch.DrawString(spriteFont, winningType, new Vector2((screenWidth / 2) - (spriteFont.MeasureString(winningType).X / 2), (screenHeight / 2) + 130), Color.White);
                spriteBatch.Draw(xboxAButton, new Rectangle(widthPadding * 2 - 64, heightPadding * 7 + 30, 64, 64), Color.White);
                spriteBatch.Draw(xboxBButton, new Rectangle(widthPadding * 8, heightPadding * 7 + 30, 64, 64), Color.White);
                spriteBatch.DrawString(spriteFont, "Restart", new Vector2(widthPadding * 2 + 12, heightPadding * 7 + 42), Color.Black);
                spriteBatch.DrawString(spriteFont, "Restart", new Vector2(widthPadding * 2 + 10, heightPadding * 7 + 40), Color.White);
                spriteBatch.DrawString(spriteFont, "Quit", new Vector2(widthPadding * 8 - 12 - spriteFont.MeasureString("Quit").X, heightPadding * 7 + 42), Color.Black);
                spriteBatch.DrawString(spriteFont, "Quit", new Vector2(widthPadding * 8 - 10 - spriteFont.MeasureString("Quit").X, heightPadding * 7 + 40), Color.White);
            }

            // Draw weather AI is thinking or not
            if (AIThinking)
            {
                float scale = 1 - ((float)Math.Sin(gameTime.TotalGameTime.TotalSeconds * 6) + 1) * 0.5f * thinkingFade;

                spriteBatch.Draw(texAI, new Rectangle(widthPadding + 120, heightPadding, 32, 32), Color.White * scale);
            }

            // Show the trading screen
            spriteBatch.Draw(gradient, new Rectangle(screenWidth - tradeWidth, heightPadding, tradeWidth, 450), new Color(0.9f, 0.9f, 0.9f, 0.9f));
            if (tradeWidth == screenWidth)    // Draw relevant icons when fully expanded
            {
                spriteBatch.Draw(texDPad, new Rectangle((screenWidth / 2) - 46, heightPadding, 92, 46), new Rectangle(0, 93, 186, 93), Color.White);

                spriteBatch.Draw(xboxAButton, new Rectangle(widthPadding * 2 - 32, 450, 64, 64), Color.White);
                spriteBatch.Draw(xboxBButton, new Rectangle(widthPadding * 4 - 32, 450, 64, 64), Color.White);
                spriteBatch.Draw(xboxXButton, new Rectangle(widthPadding * 6 - 32, 450, 64, 64), Color.White);
                spriteBatch.Draw(xboxYButton, new Rectangle(widthPadding * 8 - 32, 450, 64, 64), Color.White);

                spriteBatch.Draw(texClay, new Rectangle(widthPadding * 2 - 40, 350, 80, 80), Color.White);
                spriteBatch.Draw(texStone, new Rectangle(widthPadding * 4 - 40, 350, 80, 80), Color.White);
                spriteBatch.Draw(texWheat, new Rectangle(widthPadding * 6 - 40, 350, 80, 80), Color.White);
                spriteBatch.Draw(texWood, new Rectangle(widthPadding * 8 - 40, 350, 80, 80), Color.White);

                spriteBatch.DrawString(spriteFont, "Offering: ", new Vector2(screenWidth / 2 - 178, 198), Color.Black);
                spriteBatch.DrawString(spriteFont, "Offering: ", new Vector2(screenWidth / 2 - 180, 200), Color.White);
                switch (TradingResource)
                {
                    case HexTileResource.Clay:
                        spriteBatch.Draw(texClay, new Rectangle(screenWidth / 2 - 20, 188, 80, 80), Color.White); break;
                    case HexTileResource.Iron:
                        spriteBatch.Draw(texIron, new Rectangle(screenWidth / 2 - 20, 188, 80, 80), Color.White); break;
                    case HexTileResource.Stone:
                        spriteBatch.Draw(texStone, new Rectangle(screenWidth / 2 - 20, 188, 80, 80), Color.White); break;
                    case HexTileResource.Wheat:
                        spriteBatch.Draw(texWheat, new Rectangle(screenWidth / 2 - 20, 188, 80, 80), Color.White); break;
                    case HexTileResource.Wood:
                        spriteBatch.Draw(texWood, new Rectangle(screenWidth / 2 - 20, 188, 80, 80), Color.White); break;
                }

                spriteBatch.DrawString(spriteFont, "For: ", new Vector2(screenWidth / 2 + 80, 198), Color.Black);
                spriteBatch.DrawString(spriteFont, "For: ", new Vector2(screenWidth / 2 + 82, 200), Color.White);

                spriteBatch.DrawString(spriteFont, clayTrade + " : 1", new Vector2(widthPadding * 2 - 38, 288), Color.Black);
                spriteBatch.DrawString(spriteFont, stoneTrade + " : 1", new Vector2(widthPadding * 4 - 38, 288), Color.Black);
                spriteBatch.DrawString(spriteFont, wheatTrade + " : 1", new Vector2(widthPadding * 6 - 38, 288), Color.Black);
                spriteBatch.DrawString(spriteFont, woodTrade + " : 1", new Vector2(widthPadding * 8 - 38, 288), Color.Black);
                spriteBatch.DrawString(spriteFont, clayTrade + " : 1", new Vector2(widthPadding * 2 - 40, 290), Color.White);
                spriteBatch.DrawString(spriteFont, stoneTrade + " : 1", new Vector2(widthPadding * 4 - 40, 290), Color.White);
                spriteBatch.DrawString(spriteFont, wheatTrade + " : 1", new Vector2(widthPadding * 6 - 40, 290), Color.White);
                spriteBatch.DrawString(spriteFont, woodTrade + " : 1", new Vector2(widthPadding * 8 - 40, 290), Color.White);
            }

            spriteBatch.End();

            // draw dynamic text
            dynamicText.Draw(gameTime);

            base.Draw(gameTime);
        }

        private void DrawModel(Model model, Matrix worldTransform, Matrix[] absoluteBoneTransforms)
        {
            // nothing tricky in here; this is the same model drawing code that we see
            // everywhere. we'll loop over all of the meshes in the model, set up their
            // effects, and then draw them.
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.AmbientLightColor = Vector3.One;
                    effect.View = currentPlayer.Camera.ViewMatrix;
                    effect.Projection = currentPlayer.Camera.ProjectionMatrix;
                    effect.World = absoluteBoneTransforms[mesh.ParentBone.Index] * worldTransform;
                }
                mesh.Draw();
            }
        }

        public override void Update(GameTime gameTime)
        {
            //if (networkSession != null)
            //    ProcessPackets();

            // When changing thinking status, entries gradually fade between
            // their selected and deselected appearance, rather than instantly
            // popping to the new state.
            float fadeSpeed = (float)gameTime.ElapsedGameTime.TotalSeconds * 4;

            if (AIThinking)
                thinkingFade = Math.Min(thinkingFade + fadeSpeed, 1);
            else
                thinkingFade = Math.Max(thinkingFade - fadeSpeed, 0);

            // Update players
            foreach (KeyValuePair<PlayerColor, Player> p in players)
            {
                p.Value.Update(gameTime);
            }

            // check whether or not we need to update billboard positions
            // Just check whether we have any to update, since we assume changing must be done for a resource reason
            bool updateBillboards = (tilesToUpdate.Count > 0);

            // Incrementally update tiles' positions
            for (int i = 0; i < tilesToUpdate.Count; i++)
            {
                // Change the Y position
                if (tilesToUpdate[i].Position.Y < tilesToUpdate[i].DesiredPosition.Y)
                {
                    tilesToUpdate[i].PositionY += BoardVariables.tileElevationSpeed * gameTime.ElapsedGameTime.Milliseconds; ;
                    if (tilesToUpdate[i].Position.Y > tilesToUpdate[i].DesiredPosition.Y)
                    {
                        tilesToUpdate[i].PositionY = tilesToUpdate[i].DesiredPosition.Y;
                    }
                }
                else
                {
                    tilesToUpdate[i].PositionY -= BoardVariables.tileReductionSpeed * gameTime.ElapsedGameTime.Milliseconds; ;
                    if (tilesToUpdate[i].Position.Y < tilesToUpdate[i].DesiredPosition.Y)
                    {
                        tilesToUpdate[i].PositionY = tilesToUpdate[i].DesiredPosition.Y;
                    }
                }

                tilesToUpdate[i].naturalMatrix = Matrix.CreateRotationY(tilesToUpdate[i].naturalRotationAmount) * tilesToUpdate[i].ModelMatrix;

                // stop updating at proper height; else, update billboards so they are always on top
                if (tilesToUpdate[i].Position == tilesToUpdate[i].DesiredPosition)
                {
                    tilesToUpdate.Remove(tilesToUpdate[i]);
                }
            }

            // Update billboard heights if necessary
            if (updateBillboards)
            {
                foreach (HexTileResource r in InstancedDictionaries.resourceListProvider)
                {
                    if (r == HexTileResource.None)
                        continue;

                    billboard.AddBillboardItem(r, resourcePositions[r]);
                }
            }

            // update dynamic text
            dynamicText.Update(gameTime);

            // update particles
            cannonParticles.Update(gameTime);
            settlingParticles.Update(gameTime);

            // Rotate and "bounce" wedge over selected tile
            wedgeRotation += (float)gameTime.ElapsedGameTime.Milliseconds / 1000.0f;
            while (wedgeRotation > MathHelper.TwoPi)    // prevent from overflow float
            {
                wedgeRotation -= MathHelper.TwoPi;
            }
            wedgeElevation = 1 + (((float)Math.Sin(gameTime.TotalGameTime.TotalSeconds * 3) + 1) * 10f);// change sin internals to speed/slow

            // Slide tile selection options in and out
            if (currentPlayer.SelectedTile != null)
            {
                // Adjust wedge elevation
                wedgeElevation += currentPlayer.SelectedTile.PositionY;

                // scroll out
                if (maskWidth < maxMaskWidth)
                {
                    maskWidth += (int)(1.5f * gameTime.ElapsedGameTime.Milliseconds);

                    if (maskWidth > maxMaskWidth)
                    {
                        maskWidth = maxMaskWidth;
                    }
                }

                if (currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.Bridge || currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.DefensiveTower || currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.InfluenceTower3)
                {
                    upgradeMaskWidth -= (int)(0.8f * gameTime.ElapsedGameTime.Milliseconds);
                    if (upgradeMaskWidth < 0)
                    {
                        upgradeMaskWidth = 0;
                    }
                }
                else
                {
                    upgradeMaskWidth += (int)(1.7f * gameTime.ElapsedGameTime.Milliseconds);
                    if (upgradeMaskWidth > maxMaskWidth)
                    {
                        upgradeMaskWidth = maxMaskWidth;
                    }
                }
            }
            else if (maskWidth > 0)
            {
                // scroll in
                maskWidth -= (int)(0.9f * gameTime.ElapsedGameTime.Milliseconds);

                if (maskWidth < 0)
                {
                    maskWidth = 0;
                }

                if (upgradeMaskWidth > 0)
                {
                    upgradeMaskWidth = maskWidth;
                }
            }

            // Adjust trading gradient
            if (IsTrading)
            {
                // scroll out
                if (tradeWidth < screenWidth)
                {
                    tradeWidth += (int)(4.0f * gameTime.ElapsedGameTime.Milliseconds);

                    if (tradeWidth > screenWidth)
                    {
                        tradeWidth = screenWidth;
                    }
                }
            }
            else
            {
                // scroll in
                tradeWidth -= (int)(3.0f * gameTime.ElapsedGameTime.Milliseconds);

                if (tradeWidth < 0)
                {
                    tradeWidth = 0;
                }
            }

            // Change cursor text if need be
            // calculate a ray from the eye of the camera every n turns
            if (changeCursor == 4)
            {
                if (currentPlayer.IsAI)
                {
                    cursor.currentTexture = Cursor.CursorTexture.Select;
                }
                else
                {
                    cursorUpdateTile = null;
                    cursorUpdateRay = cursor.CalculateCursorRay(this.currentPlayer.Camera.ProjectionMatrix, this.currentPlayer.Camera.ViewMatrix);

                    // Find the tile(s)
                    this.quadtree.RetrieveClosestObject(cursorUpdateRay, ref cursorUpdateTile);

                    // Change cursor, this version does not require an attacking tower to be selected
                    if (cursorUpdateTile != null)
                    {
                        // Check if enemy tower or any bridge
                        if ((cursorUpdateTile.ManMadeModifier != HexTileManMadeModifier.None && cursorUpdateTile.tileOwner != currentPlayer.Side) || cursorUpdateTile.ManMadeModifier == HexTileManMadeModifier.Bridge)
                        {
                            // Check if we have iron and within range
                            // Influence towers can shoot farther depending on height, defensive can only shoot one height, so split
                            if (currentPlayer.CurrentResources[HexTileResource.Iron] > 0)
                            {
                                // Cannot attack defensive towers
                                if (cursorUpdateTile.ManMadeModifier == HexTileManMadeModifier.DefensiveTower)
                                {
                                    cursor.currentTexture = Cursor.CursorTexture.NoTarget;
                                    closestTileIndex = -1;
                                }
                                else
                                {
                                    cursor.currentTexture = Cursor.CursorTexture.NoTarget;
                                    closestTileIndex = -1;

                                    // Loop through our tiles, check distance for tiles, find closest tile that can attack
                                    for (int i = 0; i < currentPlayer.tilesOwned.Count; i++)
                                    {
                                        if (tiles[currentPlayer.tilesOwned[i]].ManMadeModifier != HexTileManMadeModifier.None)
                                        {
                                            if ((tiles[currentPlayer.tilesOwned[i]].ManMadeModifier != HexTileManMadeModifier.DefensiveTower && Vector3.Distance(tiles[currentPlayer.tilesOwned[i]].Position, cursorUpdateTile.Position) < (BoardVariables.cannonDistance * (int)tiles[currentPlayer.tilesOwned[i]].ManMadeModifier)) ||
                                                (tiles[currentPlayer.tilesOwned[i]].ManMadeModifier == HexTileManMadeModifier.DefensiveTower && Vector3.Distance(tiles[currentPlayer.tilesOwned[i]].Position, cursorUpdateTile.Position) < (BoardVariables.cannonDistance)))
                                            {
                                                cursor.currentTexture = Cursor.CursorTexture.Target;
                                                closestTileIndex = tiles[currentPlayer.tilesOwned[i]].IndexInBoard;
                                            }
                                        }
                                    }
                                }

                            }
                            // Else we don't have enough iron
                            else
                            {
                                cursor.currentTexture = Cursor.CursorTexture.NoTarget;
                                closestTileIndex = -1;
                            }
                        }
                        // Else friendly tower
                        else
                        {
                            cursor.currentTexture = Cursor.CursorTexture.Select;
                            closestTileIndex = -1;
                        }
                    }
                    // Else cursor tile is null, leave as select
                    else
                    {
                        cursor.currentTexture = Cursor.CursorTexture.Select;
                        closestTileIndex = -1;
                    }

                    // Change cursor, this version requires an attacking tower to be selected
                    //if (currentPlayer.SelectedTile != null && cursorUpdateTile != null
                    //    && (currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.DefensiveTower || currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.InfluenceTower1 || currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.InfluenceTower2 || currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.InfluenceTower3))
                    //{
                    //    // Check if enemy tower or any bridge
                    //    if ((cursorUpdateTile.ManMadeModifier != HexTileManMadeModifier.None && cursorUpdateTile.tileOwner != currentPlayer.Side) || cursorUpdateTile.ManMadeModifier == HexTileManMadeModifier.Bridge)
                    //    {
                    //        // Check if we have iron and within range
                    //        // Influence towers can shoot farther depending on height, defensive can only shoot one height, so split
                    //        if (currentPlayer.CurrentResources[HexTileResource.Iron] > 0)
                    //        {
                    //            // Cannot attack defensive towers
                    //            if (cursorUpdateTile.ManMadeModifier == HexTileManMadeModifier.DefensiveTower)
                    //            {
                    //                cursor.currentTexture = Cursor.CursorTexture.NoTarget;
                    //            }
                    //            else
                    //            {
                    //                if ((currentPlayer.SelectedTile.ManMadeModifier != HexTileManMadeModifier.DefensiveTower && Vector3.Distance(currentPlayer.SelectedTile.Position, cursorUpdateTile.Position) < (BoardVariables.cannonDistance * (int)currentPlayer.SelectedTile.ManMadeModifier)) ||
                    //                    (currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.DefensiveTower && Vector3.Distance(currentPlayer.SelectedTile.Position, cursorUpdateTile.Position) < (BoardVariables.cannonDistance)))
                    //                {
                    //                    cursor.currentTexture = Cursor.CursorTexture.Target;
                    //                }
                    //                else
                    //                {
                    //                    cursor.currentTexture = Cursor.CursorTexture.NoTarget;
                    //                }
                    //            }

                    //        }
                    //        else
                    //        {
                    //            cursor.currentTexture = Cursor.CursorTexture.NoTarget;
                    //        }
                    //    }
                    //    else
                    //    {
                    //        cursor.currentTexture = Cursor.CursorTexture.Select;
                    //    }
                    //}
                    //else
                    //{
                    //    cursor.currentTexture = Cursor.CursorTexture.Select;
                    //}

                    changeCursor = 0;
                }
            }
            else
            {
                changeCursor++;
            }

            // Update quadtree counts. Removed from "UPDATEINFLUENCE" to prevent multithreading issues. See function for details.
            if (InstancedDictionaries.UpdateQuadtreeCounts)
            {
                for (int i = 0; i < tiles.Length; i++)
                {
                    // try 1
                    //quadtree.RemoveColor(tiles[i], tiles[i].previousOwner);

                    // guaranteed to work try 2
                    //quadtree.RemoveColor(tiles[i], PlayerColor.Blue);
                    //quadtree.RemoveColor(tiles[i], PlayerColor.Red);
                    //quadtree.RemoveColor(tiles[i], PlayerColor.Yellow);
                    //quadtree.RemoveColor(tiles[i], PlayerColor.Green);

                    // half effort try 3
                    quadtree.RemoveColor(tiles[i], tiles[i].previousOwner);
                    quadtree.RemoveColor(tiles[i], tiles[i].tileOwner);

                    if (tiles[i].value > 0)
                    {
                        // Add to draw dictionary
                        if (tiles[i].tileOwner != PlayerColor.None)
                            quadtree.AddColorTile(tiles[i]);
                    }

                    if (tiles[i].value != tiles[i].previousValue)
                    {
                        tiles[i].DesiredPosition = new Vector3(tiles[i].Position.X, BoardVariables.tileIncrement * tiles[i].value, tiles[i].Position.Z);
                        tilesToUpdate.Add(tiles[i]);
                    }

                    // Elevate the tiles and add to dictionaries to draw
                    ////if (tiles[i].tileOwner == PlayerColor.None || tiles[i].value != tiles[i].previousValue || tiles[i].previousOwner != tiles[i].tileOwner)
                    ////{
                    //    // Change the position
                    //    if (tiles[i].value > 0)
                    //    {
                    //        // Remove from draw dictionaries
                    //        //if (tiles[i].previousOwner != PlayerColor.None || tiles[i].tileOwner != tiles[i].previousOwner || tiles[i].tileOwner == PlayerColor.None)
                    //        //{
                    //            quadtree.RemoveColor(tiles[i], tiles[i].previousOwner);
                    //        //}

                    //        // Add to be have position incrementally updated
                    //        tiles[i].DesiredPosition = new Vector3(tiles[i].Position.X, BoardVariables.tileIncrement * tiles[i].value, tiles[i].Position.Z);
                    //        tilesToUpdate.Add(tiles[i]);

                    //        // Add to draw dictionary
                    //        if (tiles[i].tileOwner != PlayerColor.None)
                    //            quadtree.AddColorTile(tiles[i]);
                    //    }
                    //    else
                    //    {
                    //        // Remove from draw dictionaries
                    //        quadtree.RemoveColor(tiles[i], tiles[i].previousOwner);

                    //        // Add to be have position incrementally updated
                    //        tiles[i].DesiredPosition = new Vector3(tiles[i].Position.X, 0, tiles[i].Position.Z);
                    //        tilesToUpdate.Add(tiles[i]);
                    //    }
                    ////}

                    // Check modifiers
                    if (tiles[i].NaturalModifier != tiles[i].PreviousNaturalModifier)
                    {
                        quadtree.RemoveNaturalModifier(tiles[i]);
                        tiles[i].PreviousNaturalModifier = tiles[i].NaturalModifier;
                    }
                    if (tiles[i].PreviousManMadeModifier != tiles[i].ManMadeModifier)
                    {
                        quadtree.RemoveManMadeModifier(tiles[i]);
                        tiles[i].PreviousManMadeModifier = tiles[i].ManMadeModifier;

                        if (tiles[i].ManMadeModifier != HexTileManMadeModifier.None)
                        {
                            quadtree.AddManmadeModifier(tiles[i]);
                        }
                        // reinsert trees hidden by building
                        else if (tiles[i].NaturalModifier == HexTileNaturalModifier.Trees1 || tiles[i].NaturalModifier == HexTileNaturalModifier.Trees1)
                        {
                            quadtree.AddNaturalModifier(tiles[i]);
                        }
                    }
                }

                InstancedDictionaries.UpdateQuadtreeCounts = false;
            }

            base.Update(gameTime);
        }

        /// <summary>
        /// Process incoming packets for local gamers.
        /// </summary>
        //private void ProcessPackets()
        //{
        //    // Check we have an active session and gamers present
        //    if ((networkSession != null) && networkSession.LocalGamers.Count > 0)
        //    {
        //        // A single local gamer can retrieve all necessary data for the local machine
        //        while (networkSession.LocalGamers[0].IsDataAvailable)
        //        {
        //            NetworkGamer sender;
        //            networkSession.LocalGamers[0].ReceiveData(packetReader, out sender);

        //            // Read the type of packet...
        //            PacketTypes packetType = (PacketTypes)packetReader.ReadInt32();

        //            // ... and dispatch accordingly
        //            switch (packetType)
        //            {
        //                case PacketTypes.GameOver:
        //                    break;
        //                case PacketTypes.InitWorld:
        //                    if (!Initialized)
        //                    {
        //                        // Get board seed
        //                        seed = packetReader.ReadInt32();

        //                        Initialized = true;
        //                        BoardConstructor.ConstructGameBoard(ref tiles, ref resourcePositions, ref billboard, dimension, seed);

        //                        // Redo stuff done initially with a new seed
        //                        TradingResource = (HexTileResource)BoardConstructor.random.Next(1, 6);
        //                        clayTrade = BoardConstructor.random.Next(2, 5);
        //                        stoneTrade = BoardConstructor.random.Next(2, 5);
        //                        wheatTrade = BoardConstructor.random.Next(2, 5);
        //                        woodTrade = BoardConstructor.random.Next(2, 5);

        //                        // Get how many players we have
        //                        int numPlayers = packetReader.ReadInt32();

        //                        // Get colors and players
        //                        // Get the gamertags and colors
        //                        // We've stored the old controller index in Blue's slot, so use that
        //                        PlayerIndex oldIndex = players[PlayerColor.Blue].playerIndex;
        //                        players = new Dictionary<PlayerColor, Player>(numPlayers);
        //                        for (int i = 0; i < networkSession.AllGamers.Count; i++)
        //                        {
        //                            packetReader.ReadString();
        //                            packetReader.ReadInt32();

        //                            players.Add((PlayerColor)i, new Player(this, (PlayerColor)i, false, oldIndex, new Vector3(tiles[tiles.Length / 2].Position.X, tiles[tiles.Length / 2].Position.Y + 400, tiles[tiles.Length / 2].Position.Z - 200), tiles[tiles.Length / 2].Position, this.Game.GraphicsDevice.Viewport));

        //                            // Track the color of the local player, of which we allow one
        //                            if (networkSession.AllGamers[i].Gamertag == networkSession.LocalGamers[0].Gamertag)
        //                            {
        //                                myColor = (PlayerColor)i;
        //                            }
        //                        }

        //                        int j = 0;
        //                        // Get starting turn
        //                        int startTurn = packetReader.ReadInt32();
        //                        foreach (KeyValuePair<PlayerColor, Player> p in players)
        //                        {
        //                            if (j == startTurn)
        //                            {
        //                                currentPlayer = p.Value;
        //                                break;
        //                            }

        //                            j++;
        //                        }
        //                    }
        //                    break;
        //                case PacketTypes.PlayerAction:
        //                    // Read player color
        //                    PlayerColor senderColor = (PlayerColor)packetReader.ReadInt32();

        //                    // Read player action
        //                    PlayerActions senderAction = (PlayerActions)packetReader.ReadInt32();

        //                    // Read source index
        //                    int sourceIndex = packetReader.ReadInt32();

        //                    // Read target index
        //                    int targetIndex = packetReader.ReadInt32();

        //                    // Execute action
        //                    switch (senderAction)
        //                    {
        //                        case PlayerActions.EndTurn:
        //                            currentPlayer.EndTurn();
        //                            dynamicText.DynamicTextLines.Add(new DynamicTextLine("It is now " + currentPlayer.ToString() + "'s turn.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("It is now " + currentPlayer.ToString() + "'s turn.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
        //                            break;
        //                        case PlayerActions.ReduceTower:
        //                            dynamicText.DynamicTextLines.Add(new DynamicTextLine(currentPlayer.ToString() + "reduced " + this.tiles[targetIndex].buildingOwner.ToString() + "'s structure.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString(currentPlayer.ToString() + "reduced " + this.tiles[targetIndex].buildingOwner.ToString() + "'s structure.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
        //                            currentPlayer.ReduceTower(sourceIndex, targetIndex);
        //                            break;
        //                        case PlayerActions.UpgradeTower:
        //                            dynamicText.DynamicTextLines.Add(new DynamicTextLine(currentPlayer.ToString() + "upgraded a tower.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString(currentPlayer.ToString() + "upgraded a tower.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
        //                            currentPlayer.UpdateTower(sourceIndex, senderColor);
        //                            break;
        //                    }

        //                    break;
        //            }
        //        }
        //    }

        //    // read the packet type
        //    // switch the packet type
        //    // execute packets by board functions
        //}

        public void HandlePlayerInput(GameTime _gameTime, InputState _input, PlayerIndex _playerIndex)
        {
            if (!Initialized)
                return;

            PCInput(_gameTime, _input, _playerIndex);
        }

        private void PCInput(GameTime _gameTime, InputState _input, PlayerIndex _playerIndex)
        {
            // ----------------------------------------------------------
            // Handle input that can be done at any time.
            // ----------------------------------------------------------
            // Rotate
            if (_input.CurrentGamePadStates[(int)_playerIndex].IsButtonDown(Buttons.LeftTrigger) || _input.CurrentKeyboardStates[(int)_playerIndex].IsKeyDown(Keys.NumPad4))
            {
                currentPlayer.Camera.RotateAroundLookatY(-cameraSpeed * Math.Max(_gameTime.ElapsedGameTime.Milliseconds, 1));
            }
            else if (_input.CurrentGamePadStates[(int)_playerIndex].IsButtonDown(Buttons.RightTrigger) || _input.CurrentKeyboardStates[(int)_playerIndex].IsKeyDown(Keys.NumPad6))
            {
                currentPlayer.Camera.RotateAroundLookatY(cameraSpeed * Math.Max(_gameTime.ElapsedGameTime.Milliseconds, 1));
            }

            // Zoom
            if (_input.CurrentGamePadStates[(int)_playerIndex].IsButtonDown(Buttons.LeftShoulder) || _input.CurrentKeyboardStates[(int)_playerIndex].IsKeyDown(Keys.NumPad7))
            {
                currentPlayer.Camera.Zoom(zoomSpeed * Math.Max(_gameTime.ElapsedGameTime.Milliseconds, 1));
            }
            else if (_input.CurrentGamePadStates[(int)_playerIndex].IsButtonDown(Buttons.RightShoulder) || _input.CurrentKeyboardStates[(int)_playerIndex].IsKeyDown(Keys.NumPad9))
            {
                currentPlayer.Camera.Zoom(-zoomSpeed * Math.Max(_gameTime.ElapsedGameTime.Milliseconds, 1));
            }

            // Translate
            if ((_input.CurrentGamePadStates[(int)_playerIndex].IsButtonDown(Buttons.LeftThumbstickUp) && cursor.Position.Y < 10) || _input.CurrentKeyboardStates[(int)_playerIndex].IsKeyDown(Keys.NumPad5))
            {
                Vector3 amount = currentPlayer.Camera.CameraDirection * translateSpeed * Math.Max(_gameTime.ElapsedGameTime.Milliseconds, 1) * (Math.Max(300, currentPlayer.Camera.CameraPosition.Y) / currentPlayer.Camera.ZoomMax);
                amount.Y = 0;
                currentPlayer.Camera.Translate(amount);
            }
            else if ((_input.CurrentGamePadStates[(int)_playerIndex].IsButtonDown(Buttons.LeftThumbstickLeft) && cursor.Position.X < 10) || _input.CurrentKeyboardStates[(int)_playerIndex].IsKeyDown(Keys.NumPad1))
            {
                Vector3 cameraRight = Vector3.Cross(Vector3.Up, currentPlayer.Camera.CameraDirection * translateSpeed * Math.Max(_gameTime.ElapsedGameTime.Milliseconds, 1) * (Math.Max(300, currentPlayer.Camera.CameraPosition.Y) / currentPlayer.Camera.ZoomMax));
                cameraRight.Y = 0;
                currentPlayer.Camera.Translate(cameraRight);
            }
            if ((_input.CurrentGamePadStates[(int)_playerIndex].IsButtonDown(Buttons.LeftThumbstickDown) && cursor.Position.Y > 710) || _input.CurrentKeyboardStates[(int)_playerIndex].IsKeyDown(Keys.NumPad2))
            {
                Vector3 amount = -currentPlayer.Camera.CameraDirection * translateSpeed * Math.Max(_gameTime.ElapsedGameTime.Milliseconds, 1) * (Math.Max(300, currentPlayer.Camera.CameraPosition.Y) / currentPlayer.Camera.ZoomMax);
                amount.Y = 0;
                currentPlayer.Camera.Translate(amount);
            }
            else if ((_input.CurrentGamePadStates[(int)_playerIndex].IsButtonDown(Buttons.LeftThumbstickRight) && cursor.Position.X > 1270) || _input.CurrentKeyboardStates[(int)_playerIndex].IsKeyDown(Keys.NumPad3))
            {
                Vector3 cameraRight = Vector3.Cross(Vector3.Up, -currentPlayer.Camera.CameraDirection * translateSpeed * Math.Max(_gameTime.ElapsedGameTime.Milliseconds, 1) * (Math.Max(300, currentPlayer.Camera.CameraPosition.Y) / currentPlayer.Camera.ZoomMax));
                cameraRight.Y = 0;
                currentPlayer.Camera.Translate(cameraRight);
            }

            if (_input.IsNewButtonPress(Buttons.LeftStick, _playerIndex) || _input.IsNewKeyPress(Keys.R, _playerIndex))
            {
                dynamicText.DynamicTextLines.Add(new DynamicTextLine("Camera reset...", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Camera reset...").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                currentPlayer.Camera.Reset(new Vector3(tiles[tiles.Length / 2].Position.X, tiles[tiles.Length / 2].Position.Y + 400, tiles[tiles.Length / 2].Position.Z - 200), tiles[tiles.Length / 2].Position);
            }

            // ----------------------------------------------------------
            // Handle input that can only be done during the player's turn
            // ----------------------------------------------------------
//#if XBOX
//            if (networkSession != null && myColor != this.currentPlayer.Side)
//                return;
//#endif

            if (IsTrading)
            {
                if (_input.IsNewButtonPress(Buttons.DPadDown, _playerIndex) || _input.IsNewKeyPress(Keys.Down, _playerIndex))
                {
                    IsTrading = false;
                }
                else if (_input.IsNewButtonPress(Buttons.A, _playerIndex) || _input.IsNewKeyPress(Keys.A, _playerIndex))
                {
                    if (TradingResource == HexTileResource.Clay)
                        return;

                    // Trade clay
                    if (this.currentPlayer.CurrentResources[HexTileResource.Clay] >= clayTrade)
                    {
                        this.currentPlayer.CurrentResources[HexTileResource.Clay] -= clayTrade;
                        dynamicText.DynamicTextLines.Add(new DynamicTextLine("-" + clayTrade, new Vector2(widthFraction + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color));

                        switch (TradingResource)
                        {
                            case HexTileResource.Clay:
                                this.currentPlayer.CurrentResources[HexTileResource.Clay]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Clay] > 99) this.currentPlayer.CurrentResources[HexTileResource.Clay] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Iron:
                                this.currentPlayer.CurrentResources[HexTileResource.Iron]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Iron] > 99) this.currentPlayer.CurrentResources[HexTileResource.Iron] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 2 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Stone:
                                this.currentPlayer.CurrentResources[HexTileResource.Stone]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Stone] > 99) this.currentPlayer.CurrentResources[HexTileResource.Stone] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 3 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Wheat:
                                this.currentPlayer.CurrentResources[HexTileResource.Wheat]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Wheat] > 99) this.currentPlayer.CurrentResources[HexTileResource.Wheat] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 4 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Wood:
                                this.currentPlayer.CurrentResources[HexTileResource.Wood]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Wood] > 99) this.currentPlayer.CurrentResources[HexTileResource.Wood] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 5 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                        }
                    }
                    else
                    {
                        // play error sound
                    }
                }
                else if (_input.IsNewButtonPress(Buttons.B, _playerIndex) || _input.IsNewKeyPress(Keys.B, _playerIndex))
                {
                    if (TradingResource == HexTileResource.Stone)
                        return;

                    // Trade clay
                    if (this.currentPlayer.CurrentResources[HexTileResource.Stone] >= stoneTrade)
                    {
                        this.currentPlayer.CurrentResources[HexTileResource.Stone] -= stoneTrade;
                        dynamicText.DynamicTextLines.Add(new DynamicTextLine("-" + stoneTrade, new Vector2(widthFraction * 3 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color));

                        switch (TradingResource)
                        {
                            case HexTileResource.Clay:
                                this.currentPlayer.CurrentResources[HexTileResource.Clay]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Clay] > 99) this.currentPlayer.CurrentResources[HexTileResource.Clay] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Iron:
                                this.currentPlayer.CurrentResources[HexTileResource.Iron]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Iron] > 99) this.currentPlayer.CurrentResources[HexTileResource.Iron] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 2 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Stone:
                                this.currentPlayer.CurrentResources[HexTileResource.Stone]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Stone] > 99) this.currentPlayer.CurrentResources[HexTileResource.Stone] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 3 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Wheat:
                                this.currentPlayer.CurrentResources[HexTileResource.Wheat]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Wheat] > 99) this.currentPlayer.CurrentResources[HexTileResource.Wheat] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 4 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Wood:
                                this.currentPlayer.CurrentResources[HexTileResource.Wood]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Wood] > 99) this.currentPlayer.CurrentResources[HexTileResource.Wood] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 5 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                        }
                    }
                    else
                    {
                        // play error sound
                    }
                }
                else if (_input.IsNewButtonPress(Buttons.X, _playerIndex) || _input.IsNewKeyPress(Keys.X, _playerIndex))
                {
                    if (TradingResource == HexTileResource.Wheat)
                        return;

                    // Trade wheat
                    if (this.currentPlayer.CurrentResources[HexTileResource.Wheat] >= wheatTrade)
                    {
                        this.currentPlayer.CurrentResources[HexTileResource.Wheat] -= wheatTrade;
                        dynamicText.DynamicTextLines.Add(new DynamicTextLine("-" + wheatTrade, new Vector2(widthFraction * 4 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color));

                        switch (TradingResource)
                        {
                            case HexTileResource.Clay:
                                this.currentPlayer.CurrentResources[HexTileResource.Clay]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Clay] > 99) this.currentPlayer.CurrentResources[HexTileResource.Clay] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Iron:
                                this.currentPlayer.CurrentResources[HexTileResource.Iron]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Iron] > 99) this.currentPlayer.CurrentResources[HexTileResource.Iron] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 2 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Stone:
                                this.currentPlayer.CurrentResources[HexTileResource.Stone]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Stone] > 99) this.currentPlayer.CurrentResources[HexTileResource.Stone] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 3 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Wheat:
                                this.currentPlayer.CurrentResources[HexTileResource.Wheat]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Wheat] > 99) this.currentPlayer.CurrentResources[HexTileResource.Wheat] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 4 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Wood:
                                this.currentPlayer.CurrentResources[HexTileResource.Wood]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Wood] > 99) this.currentPlayer.CurrentResources[HexTileResource.Wood] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 5 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                        }
                    }
                    else
                    {
                        // play error sound
                    }
                }
                else if (_input.IsNewButtonPress(Buttons.Y, _playerIndex) || _input.IsNewKeyPress(Keys.Y, _playerIndex))
                {
                    if (TradingResource == HexTileResource.Wood)
                        return;

                    // Trade wood
                    if (this.currentPlayer.CurrentResources[HexTileResource.Wood] >= woodTrade)
                    {
                        this.currentPlayer.CurrentResources[HexTileResource.Wood] -= woodTrade;
                        dynamicText.DynamicTextLines.Add(new DynamicTextLine("-" + woodTrade, new Vector2(widthFraction * 5 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color));

                        switch (TradingResource)
                        {
                            case HexTileResource.Clay:
                                this.currentPlayer.CurrentResources[HexTileResource.Clay]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Clay] > 99) this.currentPlayer.CurrentResources[HexTileResource.Clay] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Iron:
                                this.currentPlayer.CurrentResources[HexTileResource.Iron]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Iron] > 99) this.currentPlayer.CurrentResources[HexTileResource.Iron] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 2 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Stone:
                                this.currentPlayer.CurrentResources[HexTileResource.Stone]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Stone] > 99) this.currentPlayer.CurrentResources[HexTileResource.Stone] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 3 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Wheat:
                                this.currentPlayer.CurrentResources[HexTileResource.Wheat]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Wheat] > 99) this.currentPlayer.CurrentResources[HexTileResource.Wheat] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 4 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                            case HexTileResource.Wood:
                                this.currentPlayer.CurrentResources[HexTileResource.Wood]++;
                                if (this.currentPlayer.CurrentResources[HexTileResource.Wood] > 99) this.currentPlayer.CurrentResources[HexTileResource.Wood] = 99;
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("+1", new Vector2(widthFraction * 5 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, currentPlayer.color)); break;
                        }
                    }
                    else
                    {
                        // play error sound
                    }
                }
            }
            else
            {
                // Select and deselect accordingly
                if (_input.IsNewButtonPress(Buttons.A, _playerIndex) || _input.IsNewMouseLeftClick())
                {
                    // calculate a ray from the eye of the camera
                    Ray cursorRay = cursor.CalculateCursorRay(this.currentPlayer.Camera.ProjectionMatrix, this.currentPlayer.Camera.ViewMatrix);

                    // Prep an empty list of tiles
                    TileSimple closestTile = null;

                    // Find the tile(s)
                    this.quadtree.RetrieveClosestObject(cursorRay, ref closestTile);

                    // Assign to player selected tile
                    if (closestTile != null)
                    {
                        // Execute appropriate actions
                        // Enter first in order to attack bridges first
                        if (closestTileIndex > -1
                            && closestTile.ManMadeModifier == HexTileManMadeModifier.Bridge
                            && cursor.currentTexture == Cursor.CursorTexture.Target
                            && currentPlayer.CurrentResources[HexTileResource.Iron] > 0)
                        {
                            // Display loss of material
                            dynamicText.DynamicTextLines.Add(new DynamicTextLine("-1", new Vector2(widthFraction * 2 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, this.currentPlayer.color));
                            currentPlayer.CurrentResources[HexTileResource.Iron]--;

                            // Reduce tower
                            currentPlayer.ReduceTower(closestTileIndex, closestTile.IndexInBoard);
                        }
                        else if (closestTile.tileOwner == PlayerColor.None || closestTile.tileOwner == this.currentPlayer.Side)
                        {
                            // Bridges can't be selected, but reduce from here
                            if ((closestTile.TileBase == HexTileBase.Grass && (closestTile.NaturalModifier == HexTileNaturalModifier.None || closestTile.NaturalModifier == HexTileNaturalModifier.Trees1 || closestTile.NaturalModifier == HexTileNaturalModifier.Trees1 || closestTile.NaturalModifier == HexTileNaturalModifier.Hill2 || closestTile.NaturalModifier == HexTileNaturalModifier.Hill2 || closestTile.NaturalModifier == HexTileNaturalModifier.Hill2)) || closestTile.TileBase == HexTileBase.Water)
                            {
                                // Select the nearest
                                this.currentPlayer.SelectedTile = closestTile;
                            }
                            // We can't select sand or mountains
                            else
                            {
                                SoundEffect.MasterVolume = 1.0f;
                                errorSound.Play(0.2f, 0.0f, 0.0f);
                                dynamicText.DynamicTextLines.Add(new DynamicTextLine("Cannot select that tile type.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Cannot select that tile type.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                            }
                        }
                        // Enter second if guaranteed we have a friendly selected TOWER and are clicking an opposing INFLUENCE TOWER or BRIDGE
                        else if (closestTileIndex > -1
                            && cursor.currentTexture == Cursor.CursorTexture.Target
                            && currentPlayer.CurrentResources[HexTileResource.Iron] > 0)
                        {
                            // Display loss of material
                            dynamicText.DynamicTextLines.Add(new DynamicTextLine("-1", new Vector2(widthFraction * 2 + 100, heightPadding * 9 - 64), spriteFont, Color.White, 0, 1000, -Vector2.UnitY, 0.1f, 1.0f, -0.003f, 500, 0.0f, 1000, DynamicTextLine.OriginType.TopLeft, this.currentPlayer.color));
                            currentPlayer.CurrentResources[HexTileResource.Iron]--;

                            // Reduce tower
                            currentPlayer.ReduceTower(closestTileIndex, closestTile.IndexInBoard);
                        }
                        // Cannot select opposing tiles that are not towers
                        else if (closestTile.tileOwner != currentPlayer.Side && closestTile.ManMadeModifier == HexTileManMadeModifier.None)
                        {
                            errorSound.Play(0.2f, 0.0f, 0.0f);
                            dynamicText.DynamicTextLines.Add(new DynamicTextLine("Cannot select empty tiles with opposing influence.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Cannot select empty tiles with opposing influence.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                        }
                    }
                }
                else if (_input.IsNewButtonPress(Buttons.B, _playerIndex) || _input.IsNewMouseRightClick())
                {
                    // deselect all tiles
                    this.currentPlayer.SelectedTile = null;
                }
                else if (_input.IsNewButtonPress(Buttons.DPadUp, _playerIndex) || _input.IsNewKeyPress(Keys.Up, _playerIndex) && !currentPlayer.canBuildFirst)
                {
                    IsTrading = true;
                }
                else if (_input.IsNewButtonPress(Buttons.X, _playerIndex) || _input.IsNewKeyPress(Keys.X, _playerIndex))
                {
                    if (this.currentPlayer.SelectedTile != null)
                    {
                        if (this.currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.Bridge ||
                            this.currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.DefensiveTower ||
                            this.currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.InfluenceTower3)
                        {
                            errorSound.Play(0.2f, 0.0f, 0.0f);
                            this.dynamicText.DynamicTextLines.Add(new DynamicTextLine("Tile maxed out.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Tile maxed out.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                        }
                        else
                        {
                            // Place bridges only if player has already built a tower
                            if (this.currentPlayer.SelectedTile.TileBase == HexTileBase.Water)
                            {
                                if (this.currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.BridgeWoodCost &&
                                    this.currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.BridgeStoneCost &&
                                    this.currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.BridgeClayCost)
                                {
                                    if (!currentPlayer.canBuildFirst)
                                        currentPlayer.UpdateTower(currentPlayer.SelectedTile.IndexInBoard, this.currentPlayer.Side);
                                    else
                                    {
                                        errorSound.Play(0.2f, 0.0f, 0.0f);
                                        dynamicText.DynamicTextLines.Add(new DynamicTextLine("Please place initial tower.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Please place initial tower.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                                    }
                                }
                                else
                                {
                                    dynamicText.DynamicTextLines.Add(new DynamicTextLine("Insufficient resources.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Insufficient resources.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                                }
                            }
                            else if (this.currentPlayer.SelectedTile.NaturalModifier == HexTileNaturalModifier.Hill2 ||
                                this.currentPlayer.SelectedTile.NaturalModifier == HexTileNaturalModifier.Hill2 ||
                                this.currentPlayer.SelectedTile.NaturalModifier == HexTileNaturalModifier.Hill2)
                            {
                                if (this.currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.DefensiveWoodCost &&
                                    this.currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.DefensiveStoneCost &&
                                    this.currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.DefensiveClayCost)
                                {
                                    if (currentPlayer.canBuildFirst)
                                    {
                                        currentPlayer.UpdateTower(currentPlayer.SelectedTile.IndexInBoard, this.currentPlayer.Side);
                                        currentPlayer.EndTurn();
                                    }
                                    else
                                    {
                                        currentPlayer.UpdateTower(currentPlayer.SelectedTile.IndexInBoard, this.currentPlayer.Side);
                                    }
                                }
                                else
                                {
                                    errorSound.Play(0.2f, 0.0f, 0.0f);
                                    dynamicText.DynamicTextLines.Add(new DynamicTextLine("Insufficient resources.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Insufficient resources.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                                }
                            }
                            else if (this.currentPlayer.SelectedTile.TileBase == HexTileBase.Grass &&
                                this.currentPlayer.SelectedTile.NaturalModifier != HexTileNaturalModifier.Mountain1 &&
                                this.currentPlayer.SelectedTile.NaturalModifier != HexTileNaturalModifier.Mountain2 &&
                                this.currentPlayer.SelectedTile.NaturalModifier != HexTileNaturalModifier.Mountain3)
                            {
                                if (this.currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.None)
                                {
                                    if (this.currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.Influence1WoodCost &&
                                        this.currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.Influence1StoneCost &&
                                        this.currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.Influence1ClayCost &&
                                        this.currentPlayer.CurrentResources[HexTileResource.Wheat] >= BoardVariables.Influence1WheatCost)
                                    {
                                        if (currentPlayer.canBuildFirst)
                                        {
                                            currentPlayer.UpdateTower(currentPlayer.SelectedTile.IndexInBoard, this.currentPlayer.Side);
                                            currentPlayer.EndTurn();
                                        }
                                        else
                                        {
                                            currentPlayer.UpdateTower(currentPlayer.SelectedTile.IndexInBoard, this.currentPlayer.Side);
                                        }
                                    }
                                    else
                                    {
                                        errorSound.Play(0.2f, 0.0f, 0.0f);
                                        dynamicText.DynamicTextLines.Add(new DynamicTextLine("Insufficient resources.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Insufficient resources.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                                    }
                                }
                                else if (this.currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.InfluenceTower1)
                                {
                                    if (this.currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.Influence2WoodCost &&
                                        this.currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.Influence2StoneCost &&
                                        this.currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.Influence2ClayCost &&
                                        this.currentPlayer.CurrentResources[HexTileResource.Wheat] >= BoardVariables.Influence2WheatCost)
                                    {
                                        currentPlayer.UpdateTower(currentPlayer.SelectedTile.IndexInBoard, this.currentPlayer.Side);
                                    }
                                    else
                                    {
                                        errorSound.Play(0.2f, 0.0f, 0.0f);
                                        dynamicText.DynamicTextLines.Add(new DynamicTextLine("Insufficient resources.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Insufficient resources.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                                    }
                                }
                                else if (this.currentPlayer.SelectedTile.ManMadeModifier == HexTileManMadeModifier.InfluenceTower2)
                                {
                                    if (this.currentPlayer.CurrentResources[HexTileResource.Wood] >= BoardVariables.Influence3WoodCost &&
                                        this.currentPlayer.CurrentResources[HexTileResource.Stone] >= BoardVariables.Influence3StoneCost &&
                                        this.currentPlayer.CurrentResources[HexTileResource.Clay] >= BoardVariables.Influence3ClayCost &&
                                        this.currentPlayer.CurrentResources[HexTileResource.Wheat] >= BoardVariables.Influence3WheatCost)
                                    {
                                        currentPlayer.UpdateTower(currentPlayer.SelectedTile.IndexInBoard, this.currentPlayer.Side);
                                    }
                                    else
                                    {
                                        errorSound.Play(0.2f, 0.0f, 0.0f);
                                        dynamicText.DynamicTextLines.Add(new DynamicTextLine("Insufficient resources.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Insufficient resources.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // End turn can be any time
            if (!IsTrading && (_input.IsNewButtonPress(Buttons.Y, _playerIndex) || _input.IsNewKeyPress(Keys.Enter, _playerIndex)))
            {
                if (!currentPlayer.canBuildFirst)
                    currentPlayer.EndTurn();
                else
                {
                    errorSound.Play(0.2f, 0.0f, 0.0f);
                    dynamicText.DynamicTextLines.Add(new DynamicTextLine("Please place initial tower.", new Vector2((screenWidth / 2) - (spriteFontSmall.MeasureString("Please place initial tower.").X / 2), heightPadding * 6), spriteFontSmall, Color.White, 0, 2000, -Vector2.UnitY, 0.05f, 1.0f, -0.0015f, 1000, 0.0f, 2000, DynamicTextLine.OriginType.TopLeft, Color.Black));
                }
            }
        }
    }
}